#include "stdafx.h"
#include "schnorr_system.h"
#include <assert.h>


//#define __TEST

int main(int argc, char* argv[])
{

#ifdef __TEST
	const int TESTS = 10;
	typedef large_uint testsarr[TESTS];
	testsarr testp = {709,1087,599,2609,977,1213,1559,1811,2213,439},
		     testq = {59	, 181	, 23	, 163	, 61	, 101	, 41	, 181	, 79	, 73},	
			 testg = {2, 3, 7, 3, 3, 2, 19, 6, 2, 15 },	
			 testa = {551	, 729	, 103	, 830	, 101	, 457	, 1490, 508	, 769	, 331	 },	
			 
			 tests = {9	, 49	, 6	, 60	, 14	, 51	, 7	, 150	, 31	, 61	 },	
			 testv = {104	, 55	, 384	, 242	, 835	, 398	, 546	, 1755, 1685, 252	 },	
			 testr = {11	, 15	, 17	, 34	, 4	, 20	, 9	, 178	, 65	, 14	 },	
			 testx = {540	, 277	, 384	, 2376, 131	, 464	, 240	, 1372, 1956, 223	 },	
			 teste = {15	, 9	, 14	, 42	, 5	, 11	, 6	, 11	, 18	, 7	 },	
			 testy = {28, 94, 9, 109, 13, 76, 10, 18, 70, 3 };

	size_t testt[TESTS] = {4, 5, 4, 6, 3, 4, 3, 6, 5, 4 };

	for(int i = 0; i < TESTS; ++i)
	{
		schnorr_system s(testp[i],testq[i], testg[i], testt[i]);

		assert(s.get_alpha() == testa[i]);

		schnorr_prover prover(tests[i], &s);

		assert(prover.get_public() == testv[i]);

		large_uint x = prover.get_witness(testr[i]);

		assert(x == testx[i]);

		large_uint y = prover.get_response(teste[i]);

		assert(y == testy[i]);
		
		s.set_prover(&prover);

		bool result = s.verify(x,y,teste[i]);

		assert(result == true);

		//printf("%i. %sauth.\n", i, result? "":"not "); 
	}
#else /*__TEST*/
 

		printf("1. Generate the parameters of the scheme...\n");
		schnorr_system s;

		printf("\n2. Generate the parameters of the prover...\n");
		schnorr_prover prover(&s);
		s.set_prover(&prover);

		printf("\n3. Prover sends a witness to verifyer.\n");
		large_uint x = prover.get_witness();
		printf("\n P -> V: x = (alpha ^ r) %% p = (%I64u; %I64u)\n", x._h,x._l);


		printf("\n4. Verifyer sends a challenge of size t = %i to prover.\n", s.get_security_param());
		large_uint e = large_uint::random() % (large_uint::one() << s.get_security_param());
		printf("\n V -> P: e = (%I64u; %I64u)\n", e._h,e._l);

		printf("\n5. Prover sends a response to verifyer.\n");
		large_uint y = prover.get_response(e);
		printf("\n P -> V: y = (r + s*e) %% q = (%I64u; %I64u)\n", y._h, y._l);

		printf("\n6. Verifyer verify prover by comparing.\n");
		bool result = s.verify(x,y,e);
		printf("\n V: \"P is %s\"\n", result ? "friend":"foe");

		/*
		x = alpha^r mod p
		v = alpha^(-s) mod p
		y = (r + s*e) mod q

		x' = (alpha^y * v^e) mod p = (alpha^((r + s*e) mod q) * (alpha^(-s) mod p)^e ) mod p
		= alpha^r * alpha^(s*e)* alpha^(-s*e) mod p = alpha^r mod p = x
	    */
#endif
	return 0;
}
